package com.ksyun.campus.metaserver.services;

import com.ksyun.campus.metaserver.domain.DataServerInfo;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class RegistService implements ApplicationRunner {

    @Value("${server.port}")
    private String port;

    @Value("${server.ip}")
    private String ip;

    @Value("${server.connectString}")
    private String connectString;

    private CuratorFramework client;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(500, 5);
        //RetryPolicy retryPolicy = new RetryForever(500);

        client = CuratorFrameworkFactory.builder().connectString(connectString) //虚拟机地址
                .sessionTimeoutMs(15 * 1000)
                .connectionTimeoutMs(15 * 1000)
                .retryPolicy(retryPolicy)
                //.namespace() //命名空间
                .build();

        System.out.println("开始启动client");
        long startTime = System.currentTimeMillis(); // 记录开始时间
        client.start(); //很耗时间
        System.out.println("启动成功client");
        long endTime = System.currentTimeMillis(); // 记录结束时间
        long duration = (endTime - startTime) / 1000; // 计算耗时（秒）
        System.out.println("启动耗时: " + duration + "秒");

        registToCenter();


    }

    public void registToCenter() throws Exception {
        System.out.println("开始注册节点");
        long startTime = System.currentTimeMillis(); // 记录开始时间
        // todo 将本实例信息注册至zk中心，包含信息 ip、port
        String data = ip + "," + port;
        String path = "/server/metaServer/metaServerInstance";
        client.create().creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL_SEQUENTIAL)
                .forPath(path, data.getBytes());


        System.out.println("成功注册节点");
        long endTime = System.currentTimeMillis(); // 记录结束时间
        long duration = (endTime - startTime) / 1000; // 计算耗时（秒）
        System.out.println("注册耗时: " + duration + "秒");
    }

    public List<DataServerInfo> getDslist() {
        List<DataServerInfo> dataServerList = new ArrayList<>();
        String path = "/server/dataServer";

        try {
            // 获取 /server/dataServer 下的所有子节点
            List<String> children = client.getChildren().forPath(path);

            // 遍历每个子节点，获取其数据并封装成 DataServerInfo 对象
            for (String child : children) {
                String childPath = path + "/" + child;
                byte[] data = client.getData().forPath(childPath);

                //data 是一个字符串，格式为 "ip,port"
                String dataStr = new String(data);
                String[] parts = dataStr.split(",");

                String ip = parts[0];
                String port = parts[1];
                String azname = parts[2];
                String rack = parts[3];
                String zone = parts[4];
                DataServerInfo serverInfo = new DataServerInfo();
                serverInfo.setIpAddress(ip);
                serverInfo.setPort(Integer.parseInt(port));
                serverInfo.setAzname(azname);
                serverInfo.setRack(rack);
                serverInfo.setZone(zone);
                dataServerList.add(serverInfo);

            }
        } catch (Exception e) {
            e.printStackTrace();  // 打印异常信息
        }

        return dataServerList;
    }


    public void closeZKClient() {
        if (client != null) {
            System.out.println("开始关闭client");
            long startTime = System.currentTimeMillis(); // 记录开始时间
            client.close();
            System.out.println("成功关闭client");
            long endTime = System.currentTimeMillis(); // 记录结束时间
            long duration = (endTime - startTime) / 1000; // 计算耗时（秒）
            System.out.println("关闭耗时: " + duration + "秒");
        }
    }


}
